package com.cloud.screen.api.service.impl;

import com.cloud.screen.api.entity.ScreenReqInfo;
import com.cloud.screen.api.entity.UnitInfo;
import com.cloud.screen.api.mapper.UnitInfoMapper;
import com.cloud.screen.api.service.PunishService;
import com.cloud.screen.common.utils.DateHelper;
import com.cloud.screen.interfaces.FeignClientPunish;
import com.cloud.screen.interfaces.FeignClientSystem;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by sl on 2019/6/26.
 */
@Service
@Transactional
public class PunishServiceImpl implements PunishService{

    @Autowired
    private FeignClientPunish feignClientPunish;

    @Autowired
    private FeignClientSystem feignClientSystem;

    @Autowired
    private UnitInfoMapper unitInfoMapper;

    private static final Integer SELECT_HOUR = 1;
    private static final Integer SELECT_WEEK= 3;
    private static final Integer SELECT_QUARTER = 5;
    private static final Integer SELECT_HALFYAER = 6;

    @Override
    public List<Map<String, Object>> getLegalCaseInfo(String start ,String end,Long regionid,Integer type,Integer recType) {
        type = type == null?1:type;
        UnitInfo unit = unitInfoMapper.selectByPrimaryKey(regionid == null?1:regionid);
        ScreenReqInfo info = new ScreenReqInfo();
        info.setStart(start);
        info.setEnd(end);
        info.setUnitCode(unit.getUnitCode());
        info.setType(type);
        info.setRecType(recType);
        List<Map<String, Object>> list = feignClientPunish.getRecPunishByDate(info);
        if (list != null){
            if (type .equals(SELECT_HOUR)){
                List<String> dateList = DateHelper.getDateList();
                List<String> stringList = new ArrayList<>();
                list.forEach(v->{
                    stringList.add(v.get("timeRange").toString());
                });
                stringList.forEach(c->{
                    dateList.removeIf(s -> s.contains(c));
                });
                List<Map<String, Object>> finalQueryForList = list;
                dateList.forEach(k->{
                    Map<String,Object> map = new HashMap<>();
                    map.put("count",0);
                    map.put("timeRange",k);
                    finalQueryForList.add(map);
                });
            } else if (type.equals(SELECT_WEEK)){
                list.forEach(v->{
                    v.put("timeRange", DateHelper.getWeekDays(DateHelper.strToDate(v.get("timeRange").toString())));
                });
                list = list.stream().collect(Collectors.groupingBy(e -> e.get("timeRange")))
                        .entrySet().stream().map(e -> {
                            Map<String, Object> map = new HashMap<>();
                            map.put("count", e.getValue().size());
                            map.put("timeRange", e.getKey());
                            return map;
                        }).collect(Collectors.toList());
            } else if (type.equals(SELECT_QUARTER)) {
                Map<String, Map<String, Object>> times = new HashMap<>();
                list.forEach(v -> {
                    String quarter = DateHelper.monthToQuarter(v.get("timeRange").toString());
                    Map<String, Object> item = times.get(quarter);
                    if (item == null) {
                        item = new HashedMap();
                        item.put("count", 0);
                        item.put("timeRange", quarter);
                    }
                    Long count = item.get("count") == null ? 0 : Long.parseLong(item.get("count").toString());
                    count += v.get("count") == null ? 0 : Long.parseLong(v.get("count").toString());
                    item.put("count", count);
                    times.put(quarter, item);
                });
                list = new ArrayList<>(times.values());
            } else if (type.equals(SELECT_HALFYAER)) {
                Map<String, Map<String, Object>> times = new HashMap<>();
                list.forEach(v -> {
                    String half = DateHelper.monthToHalfYear(v.get("timeRange").toString());
                    Map<String, Object> item = times.get(half);
                    if (item == null) {
                        item = new HashedMap();
                        item.put("count", 0);
                        item.put("timeRange", half);
                    }
                    Long count = item.get("count") == null ? 0 : Long.parseLong(item.get("count").toString());
                    count += v.get("count") == null ? 0 : Long.parseLong(v.get("count").toString());
                    item.put("count", count);
                    times.put(half, item);
                });
                list = new ArrayList<>(times.values());
            }
            list.sort(Comparator.comparing(o -> o.get("timeRange").toString()));
        }
        return list;
    }

    @Override
    public List<Map<String, Object>> getLegalCaseSource(String start, String end, Long regionid,Integer recType) {
        UnitInfo unit = unitInfoMapper.selectByPrimaryKey(regionid == null?1:regionid);
        ScreenReqInfo info = new ScreenReqInfo();
        info.setStart(start);
        info.setEnd(end);
        info.setUnitCode(unit.getUnitCode());
        info.setRecType(recType);
        return feignClientPunish.getLegalCaseSource(info);
    }

    @Override
    public Map<String, Object> getLegalCaseRegion(String start, String end, Long regionid, Integer recType) {
        UnitInfo unit = unitInfoMapper.selectByPrimaryKey(regionid == null?1:regionid);
        List<Map<String, Object>> unitInfos =  feignClientSystem.getUnitInfoForProvince(regionid == null?1:regionid);
        ScreenReqInfo info = new ScreenReqInfo();
        info.setStart(start);
        info.setEnd(end);
        info.setUnitCode(unit.getUnitCode());
        info.setRegionCode(unit.getRegionCode());
        info.setRecType(recType);
        List<Map<String, Object>> domainList =  feignClientPunish.getLegalCaseRegion(info);
        Map<String, Object> returnList = new HashMap<>();
        if ( unitInfos != null && domainList != null){
            unitInfos.addAll(domainList);
            List<Map<String, Object>> result = unitInfos.stream().collect(Collectors.groupingBy(e -> e.get("region_code")))
                    .entrySet().stream().map(e -> {
                        Map<String, Object> map = new HashMap<>();
                        map.put("regionid", e.getValue().get(0).get("unit_id"));
                        map.put("regionname", e.getValue().get(0).get("unit_name"));
                        map.put("seniorid", e.getValue().get(0).get("senior_id"));
                        if (e.getValue().size()>1){
                            map.put("sumnum", e.getValue().get(1).get("count")==null?0:e.getValue().get(1).get("count"));
                        }else {
                            map.put("sumnum", 0);
                        }
                        map.put("regioncode", regionIdFormat(e.getKey().toString()));
                        return map;
                    }).collect(Collectors.toList());
            UnitInfo unitInfo = getRegionInfo(unit.getRegionCode());
            //封装返回格式
            final int[] i = {0};
            result.forEach(sun -> {
                i[0] += Integer.parseInt(sun.get("sumnum")==null?"0":sun.get("sumnum").toString());
            });
            
            Map<String, Object> statMap = new HashMap<>();
            Map<String, Object> regionMap = new HashMap<>();
            regionMap.put("regionid", unitInfo.getUnitId());
            regionMap.put("regioncode", regionIdFormat(unitInfo.getRegionCode()));
            regionMap.put("regionname", unitInfo.getUnitName());
            regionMap.put("sumnum", i[0]);
            regionMap.put("seniorid", unitInfo.getSeniorId());
            statMap.put("region", regionMap);
            statMap.put("children", result);
            returnList.put("stat", statMap);
        }
        return returnList;
    }

    @Override
    public List<Map<String, Object>> getLegalCaseDomain(String start, String end, Long regionid, Integer recType, Integer num) {
        UnitInfo unit = unitInfoMapper.selectByPrimaryKey(regionid == null?1:regionid);
        ScreenReqInfo info = new ScreenReqInfo();
        info.setStart(start);
        info.setEnd(end);
        info.setUnitCode(unit.getUnitCode());
        info.setRecType(recType);
        info.setNum(num);
        List<Map<String,Object>> mapList =  feignClientPunish.getLegalCaseDomain(info);
        List<Map<String,Object>> returnList = new ArrayList<>();
        if (mapList != null){
            mapList.forEach(map->{
                String [] nameList = map.get("timeRange").toString().split(",");
                if (nameList.length > 1){
                    for (int i = 0 ;i< nameList.length; i++ ){
                        Map<String,Object> stringObjectMap = new HashMap<>();
                        stringObjectMap.put("count",map.get("count"));
                        stringObjectMap.put("timeRange",nameList[i]);
                        returnList.add(stringObjectMap);
                    }
                }else {
                    returnList.add(map);
                }
            });
        }
        Map<String, List<Map<String, Object>>> glist = returnList.stream().collect(Collectors.groupingBy(e -> e.get("timeRange").toString()));
        List<Map<String,Object>> result = new ArrayList<>();
        glist.forEach((k,slist)->{
            Map<String,Object> nmap=new HashMap<>();
            IntSummaryStatistics sumcc = slist.stream().collect(Collectors.summarizingInt(e->Integer.valueOf(e.get("count").toString())));
            nmap.put("timeRange", slist.get(0).get("timeRange"));
            nmap.put("count", sumcc.getSum());
            //求和
            result.add(nmap);
        });
        return  result;
    }

    @Override
    public Map<String, Object> getLegalCaseGeneral(String start, String end,Long regionid) {
        UnitInfo unit = unitInfoMapper.selectByPrimaryKey(regionid == null?1:regionid);
        ScreenReqInfo info = new ScreenReqInfo();
        info.setStart(start);
        info.setEnd(end);
        info.setUnitCode(unit.getUnitCode());
        return feignClientPunish.getLegalCaseGeneral(info);
    }

    @Override
    public List<Map<String, Object>> getLawCaseTop5(String start, String end, Long regionid, Integer recType) {
        UnitInfo unit = unitInfoMapper.selectByPrimaryKey(regionid == null?1:regionid);
        ScreenReqInfo info = new ScreenReqInfo();
        info.setStart(start);
        info.setEnd(end);
        info.setUnitCode(unit.getUnitCode());
        info.setRecType(recType);
        return feignClientPunish.getLawCaseTop5(info);
    }

    @Override
    public List<Map<String, Object>> getLawCaseTop(String start, String end, Long regionid, Integer num) {
        UnitInfo unit = unitInfoMapper.selectByPrimaryKey(regionid == null?1:regionid);
        ScreenReqInfo info = new ScreenReqInfo();
        info.setStart(start);
        info.setEnd(end);
        info.setUnitCode(unit.getUnitCode());
        info.setNum(num);
        return feignClientPunish.getLawCaseTop(info);
    }

    @Override
    public List<Map<String, Object>> getLawUseStat(String start, String end, Long regionid) {
        UnitInfo unit = unitInfoMapper.selectByPrimaryKey(regionid == null?1:regionid);
        ScreenReqInfo info = new ScreenReqInfo();
        info.setStart(start);
        info.setEnd(end);
        info.setUnitCode(unit.getUnitCode());
        return feignClientPunish.getLawUseStat(info);
    }

    @Override
    public List<Map<String, Object>> getCauseUseStat(String start, String end, Long regionid, String lawID) {
        UnitInfo unit = unitInfoMapper.selectByPrimaryKey(regionid == null?1:regionid);
        ScreenReqInfo info = new ScreenReqInfo();
        info.setStart(start);
        info.setEnd(end);
        info.setUnitCode(unit.getUnitCode());
        info.setLawID(lawID);
        return feignClientPunish.getCauseUseStat(info);
    }

    @Override
    public List<Map<String, Object>> getPunishByRegionId(ScreenReqInfo info) {
        UnitInfo unit = unitInfoMapper.selectByPrimaryKey(info.getRegionid() == null?1:info.getRegionid());
        info.setUnitCode(unit.getUnitCode());
        return feignClientPunish.getPunishByRegionId(info);
    }


    private UnitInfo getRegionInfo(String regionCode) {
        Example example = new Example(UnitInfo.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("regionCode", regionCode);
        criteria.andEqualTo("unitTypeId", 0);
        return unitInfoMapper.selectByExample(example).get(0);
    }
    private String regionIdFormat(String regionId) {
        int n = 6;
        if (StringUtils.isNotBlank(regionId) && regionId.length()<n){
            return regionId+String.format("%1$0"+(n-regionId.length())+"d",0);
        }
        return regionId;
    }
}
